import os
import wx
import wx.lib.stattext

# ---------------------------------------------------------------------------- #
# Class ArtManager
# ---------------------------------------------------------------------------- #

class ArtManager(wx.EvtHandler):

    """
    This class provides various art utilities, such as creating shadow, providing
    lighter / darker colors for a given color, etc...
    """
    test = 0
    def __init__(self):
        """ Default class constructor. """

        wx.EvtHandler.__init__(self)
        self._menuBarBgColour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE)


    def Get(self):

        if not hasattr(self, "_instance"):
            self._instance = ArtManager()
            
        return self._instance

    Get = classmethod(Get)
    
    def Free(self):

        if hasattr(self, "_instance"):
        
            del self._instance

    Free = classmethod(Free)

    def getThemeColor(self):
        color = utility.config.Read('theme_color', "color")
        return color
    
    def isDefTheme(self):
        return self.getThemeColor() == wx.WHITE
    
    def makeBoldText(self, txt):
        self.setTextWeight(txt, wx.FONTWEIGHT_BOLD)
        
    def makeNormalText(self, txt):
        self.setTextWeight(txt, wx.FONTWEIGHT_NORMAL)
        
    def setTextWeight(self, txt, weight):
        """
        Set Text weight
        @param txt = wx.StaticText object
        """
        font = txt.GetFont()
        font.SetWeight(weight)
        txt.SetFont(font)

    def makeSeparator(self, panel, box):
        """
        Adds a separator to Sizer
        """
        box.Add(wx.StaticLine(panel, -1, style = wx.LI_VERTICAL), 0,
                wx.GROW|wx.ALIGN_CENTER_VERTICAL|wx.LEFT|wx.RIGHT, 5)
            
    def makeFlatButton(self, panel, text, func, first = False):
        """
        Gets wx.StaticText object and return a flat button
        """
        def makeNormal(event):
            ArtManager.Get().makeNormalText(button)
            panel.Layout()
        def makeBold(event):
            ArtManager.Get().makeBoldText(button)
            panel.Layout()
            
        buttonSizer = wx.BoxSizer(wx.HORIZONTAL)
        if first:
            self.makeSeparator(panel, buttonSizer)
        button = wx.lib.stattext.GenStaticText(panel, -1, text)
        button.Bind(wx.EVT_LEAVE_WINDOW, makeNormal)
        button.Bind(wx.EVT_ENTER_WINDOW, makeBold)
        button.Bind(wx.EVT_LEFT_DOWN, func)
        buttonSizer.Add(button, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 3)
        self.makeSeparator(panel, buttonSizer)
        return buttonSizer

    def LightColour(self, color, percent):
        """
        Return light contrast of color. The color returned is from the scale of
        color -> white. The percent determines how light the color will be.
        Percent = 100 return white, percent = 0 returns color.
        """

        end_color = wx.WHITE
        rd = end_color.Red() - color.Red()
        gd = end_color.Green() - color.Green()
        bd = end_color.Blue() - color.Blue()
        high = 100

        # We take the percent way of the color from color -. white
        i = percent
        r = color.Red() + ((i*rd*100)/high)/100
        g = color.Green() + ((i*gd*100)/high)/100
        b = color.Blue() + ((i*bd*100)/high)/100

        return wx.Colour(r, g, b)

    def DarkColour(self, color, percent):
        """ Like the LightColour() function, but create the color darker by percent. """

        end_color = wx.BLACK
        rd = end_color.Red() - color.Red()
        gd = end_color.Green() - color.Green()
        bd = end_color.Blue() - color.Blue()
        high = 100

        # We take the percent way of the color from color -. white
        i = percent
        r = color.Red() + ((i*rd*100)/high)/100
        g = color.Green() + ((i*gd*100)/high)/100
        b = color.Blue() + ((i*bd*100)/high)/100

        return wx.Colour(r, g, b)


    def FrameColour(self):
        """ Return the surrounding color for a control. """

        return wx.SystemSettings_GetColour(wx.SYS_COLOUR_ACTIVECAPTION)


    def BackgroundColor(self):
        """ Returns the background color of a control when not in focus. """

        return self.LightColour(self.FrameColour(), 75)


    def HighlightBackgroundColor(self):
        """ Returns the background color of a control when it is in focus. """

        return self.LightColour(self.FrameColour(), 60)


    def MixColors(self, firstColor, secondColor, percent):
        """ Return mix of input colors. """

        # calculate gradient coefficients
        redOffset = float((secondColor.Red() * (100 - percent) / 100) - (firstColor.Red() * percent / 100))
        greenOffset = float((secondColor.Green() * (100 - percent) / 100) - (firstColor.Green() * percent / 100))
        blueOffset = float((secondColor.Blue() * (100 - percent) / 100) -  (firstColor.Blue() * percent / 100))

        return wx.Colour(firstColor.Red() + redOffset, firstColor.Green() + greenOffset,
                        firstColor.Blue() + blueOffset)


    def RandomColour(): 
        """ Creates a random colour. """
        
        r = random.randint(0, 255) # Random value betweem 0-255
        g = random.randint(0, 255) # Random value betweem 0-255
        b = random.randint(0, 255) # Random value betweem 0-255

        return wx.Colour(r, g, b)


    def IsDark(self, color):
        """ Returns whether a color is dark or light. """

        evg = (color.Red() + color.Green() + color.Blue())/3
        
        if evg < 127:
            return True

        return False


    def TruncateText(self, dc, text, maxWidth):
        """
        Truncates a given string to fit given width size. if the text does not fit
        into the given width it is truncated to fit. the format of the fixed text
        is <truncate text ..>.
        """

        textLen = len(text)
        tempText = text
        rectSize = maxWidth

        fixedText = ""
        
        textW, textH = dc.GetTextExtent(text)

        if rectSize >= textW:        
            return text
        
        # The text does not fit in the designated area, 
        # so we need to truncate it a bit
        suffix = ".."
        w, h = dc.GetTextExtent(suffix)
        rectSize -= w

        for i in xrange(textLen, -1, -1):
        
            textW, textH = dc.GetTextExtent(tempText)
            if rectSize >= textW:
                fixedText = tempText
                fixedText += ".."
                return fixedText
            
            tempText = tempText[:-1]    

    def GetMenuFaceColour(self):
        " Returns the colour used for menu face. """
        return self.LightColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE), 80)

    def GetEvenRowColor(self, list):
        if wx.Platform == "__WXMAC__":
            backBrush = wx.Brush(wx.MacThemeColour(57))
            color = backBrush.GetColour()
        else:
            color = self.DarkColour(list.GetBackgroundColour(), 5)
        return color

    def GetOddRowColor(self, list):
        if wx.Platform == "__WXMAC__":
            backBrush = wx.Brush(wx.MacThemeColour(56))
            color = backBrush.GetColour()
        else:
            color = list.GetBackgroundColour()
        return color

    def MakeAlternateList(self, list):
        if not isinstance(list, wx.ListCtrl):
            return
        if hasattr(list, "MakeAlternateList"):
            list.MakeAlternateList(self.GetEvenRowColor(list))
            return
        odd = self.GetOddRowColor(list)
        even = self.GetEvenRowColor(list)
        for i in xrange(list.GetItemCount()):
            if i % 2:
                list.SetItemBackgroundColour(i, even)
            else:
                list.SetItemBackgroundColour(i, odd)

    def MakeAlternateListItem(self, list, item):
        if item % 2:
            list.SetItemBackgroundColour(item, self.GetEvenRowColor(list))
        else:
            list.SetItemBackgroundColour(item, self.GetOddRowColor(list))
